package org.dromara.hm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.service.DeptService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.hm.domain.HmIssueReceiptRecords;
import org.dromara.hm.domain.HmSaleOrder;
import org.dromara.hm.domain.HmSaleOrderPickUp;
import org.dromara.hm.domain.HmStock;
import org.dromara.hm.domain.HmSupplementaryPickupRecord;
import org.dromara.hm.domain.bo.HmStockBo;
import org.dromara.hm.domain.bo.HmStockChangeBo;
import org.dromara.hm.domain.vo.HmCustomerVo;
import org.dromara.hm.domain.vo.HmStockVo;
import org.dromara.hm.domain.vo.StockChangeRecordVO;
import org.dromara.hm.enums.OrderStatus;
import org.dromara.hm.enums.PickUpStatusEnum;
import org.dromara.hm.enums.ReceiptIssueRecordTypeEnum;
import org.dromara.hm.enums.StockChangeTypeEnum;
import org.dromara.hm.enums.StockTypeEnum;
import org.dromara.hm.mapper.HmCustomerMapper;
import org.dromara.hm.mapper.HmIssueReceiptRecordsMapper;
import org.dromara.hm.mapper.saleOrder.HmSaleOrderMapper;
import org.dromara.hm.mapper.saleOrder.HmSaleOrderPickUpMapper;
import org.dromara.hm.mapper.HmStockMapper;
import org.dromara.hm.mapper.saleOrder.HmSupplementaryPickupRecordMapper;
import org.dromara.hm.service.IHmProductService;
import org.dromara.hm.service.IHmStockChangeService;
import org.dromara.hm.service.IHmStockService;
import org.dromara.system.service.ISysDeptService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 库存数据Service业务层处理
 *
 * @author zy Hu
 * @date 2024-12-15
 */
@RequiredArgsConstructor
@Service
public class HmStockServiceImpl implements IHmStockService
{

    private final HmStockMapper baseMapper;

    // 出入库记录Mapper
    private final HmIssueReceiptRecordsMapper issueReceiptRecordsMapper;

    // 补充提货记录Mapper
    private final HmSupplementaryPickupRecordMapper supplementaryPickupRecordMapper;

    // 提货记录Mapper
    private final HmSaleOrderPickUpMapper saleOrderPickUpMapper;

    // 销售单Mapper
    private final HmSaleOrderMapper saleOrderMapper;

    // 店铺Mapper
    private final ISysDeptService deptService;

    private final DeptService translationDeptService;

    private final IHmProductService productService;

    private final IHmStockChangeService hmStockChangeService;

    private final HmCustomerMapper customerMapper;

    /**
     * 查询库存数据
     *
     * @param stockId 主键
     *
     * @return 库存数据
     */
    @Override
    public HmStockVo queryById(Long stockId)
    {
        return baseMapper.selectVoById(stockId);
    }

    /**
     * 分页查询库存数据列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     *
     * @return 库存数据分页列表
     */
    @Override
    public TableDataInfo<HmStockVo> queryPageList(HmStockBo bo, PageQuery pageQuery)
    {
        LambdaQueryWrapper<HmStock> lqw = buildQueryWrapper(bo);
        Page<HmStockVo> result;
        List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
        List<String> roleNames = roles.stream().map(RoleDTO::getRoleKey).toList();
        if (roleNames.contains("warehouse"))
        {
            lqw.eq(HmStock::getProductDept, LoginHelper.getDeptId());
            result = DataPermissionHelper.ignore(()-> baseMapper.selectVoPage(pageQuery.build(), lqw));
        }else{
            result  = baseMapper.selectVoPage(pageQuery.build(), lqw);

        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的库存数据列表
     *
     * @param bo 查询条件
     *
     * @return 库存数据列表
     */
    @Override
    public List<HmStockVo> queryList(HmStockBo bo)
    {
        LambdaQueryWrapper<HmStock> lqw = buildQueryWrapper(bo);
        List<HmStockVo> hmStockVos = baseMapper.selectVoList(lqw);
        // 翻译库存所在门店名称
        hmStockVos.forEach(stockVo -> {
            // 翻译店铺名称
            stockVo.setProductDeptName(translationDeptService.selectDeptNameByIds(stockVo.getProductDept().toString()));
            // 翻译商品名称
            stockVo.setStockProductName(productService.queryById(stockVo.getStockProductId()).getProductName());
        });
        return hmStockVos;
    }

    private LambdaQueryWrapper<HmStock> buildQueryWrapper(HmStockBo bo)
    {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HmStock> lqw = Wrappers.lambdaQuery();

        lqw.eq(bo.getProductDept() != null, HmStock::getProductDept, bo.getProductDept());
        lqw.eq(bo.getStockId() != null, HmStock::getStockId, bo.getStockId());
        lqw.eq(bo.getStockProductId() != null, HmStock::getStockProductId, bo.getStockProductId());
        lqw.like(StringUtils.isNotBlank(bo.getStockProductName()), HmStock::getStockProductName, bo.getStockProductName());
        lqw.eq(bo.getStockNum() != null, HmStock::getStockNum, bo.getStockNum());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), HmStock::getStatus, bo.getStatus());
        lqw.orderByDesc(HmStock::getProductDept);
        return lqw;
    }

    /**
     * 新增库存数据
     *
     * @param bo 库存数据
     *
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(HmStockBo bo)
    {
        HmStock add = MapstructUtils.convert(bo, HmStock.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag)
        {
            bo.setStockId(add.getStockId());
        }
        // 新增库存变更历史记录
        HmStockChangeBo hmStockChangeBo = new HmStockChangeBo();
        hmStockChangeBo.setStockId(add.getStockId()); // 库存id
        hmStockChangeBo.setChangeType(StockChangeTypeEnum.ADD.getCode()); // 变更类型
        hmStockChangeBo.setChangeInfo(StockChangeTypeEnum.ADD.getDescription()); // 变更详情
        hmStockChangeBo.setChangeNum(add.getStockNum());// 变更数量
        hmStockChangeBo.setChangeTime(new Date()); // 变更时间
        hmStockChangeBo.setProductId(String.valueOf(bo.getStockProductId())); // 变更商品id
        hmStockChangeBo.setRemark(bo.getRemark()); //备注
        hmStockChangeService.insertByBo(hmStockChangeBo);
        return flag;
    }

    /**
     * 修改库存数据
     *
     * @param bo 库存数据
     *
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(HmStockBo bo)
    {
        HmStock update = MapstructUtils.convert(bo, HmStock.class);
        // 当前修改的数量与原库存数量进行减法运算,判断是增加还是减少.若为正数则为增加,类型为ADD.若为负数则为减少,类型为REDUCE.
        HmStock old = baseMapper.selectById(bo.getStockId());
        int i = bo.getStockNum().subtract(old.getStockNum()).intValue();
        if(i != 0){
            // 修改库存变更历史记录
            HmStockChangeBo hmStockChangeBo = new HmStockChangeBo();
            hmStockChangeBo.setStockId(bo.getStockId()); // 库存id
            if(!PickUpStatusEnum.CANCEL.getDescription().equals(bo.getSign())){
                hmStockChangeBo.setChangeType(i>0?StockChangeTypeEnum.ADD.getCode():StockChangeTypeEnum.REDUCE.getCode()); // 变更类型
                hmStockChangeBo.setChangeInfo(i>0?StockChangeTypeEnum.ADD.getDescription():StockChangeTypeEnum.REDUCE.getDescription()); // 变更详情
                hmStockChangeBo.setOperatorId(String.valueOf(Objects.requireNonNull(LoginHelper.getLoginUser()).getUserId()));
                hmStockChangeBo.setOperator(Objects.requireNonNull(LoginHelper.getLoginUser()).getNickname());
                hmStockChangeBo.setRemark(bo.getRemark()); //备注
                hmStockChangeBo.setChangeNum(BigDecimal.valueOf(Math.abs(i)));// 变更数量
                hmStockChangeBo.setChangeTime(new Date()); // 变更时间
                hmStockChangeBo.setProductId(String.valueOf(bo.getStockProductId())); // 变更商品id
                hmStockChangeService.insertByBo(hmStockChangeBo);
            }

        }
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 提货修改库存
     * @param bo
     * @return
     */
    @Override
    public Boolean pickUpUpdateByBo(HmStockBo bo)
    {
        HmStock update = MapstructUtils.convert(bo, HmStock.class);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HmStock entity)
    {
        // 判断当前产品和店铺是否存储数据
        HmStockVo hmStockVo = queryByProductIdAndDeptId(entity.getStockProductId(), entity.getProductDept());
    }

    /**
     * 校验并批量删除库存数据信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     *
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid)
    {
        if (isValid)
        {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public HmStockVo queryByProductIdAndDeptId(Long productId, Long deptId)
    {
        return baseMapper.selectVoOne(Wrappers.lambdaQuery(HmStock.class).eq(HmStock::getStockProductId, productId).eq(HmStock::getProductDept, deptId));
    }

    /**
     * 查询库存变更记录
     *
     * @param productId 商品ID
     * @param storeId   店铺ID
     * @param productType 筛选的产品类型 ("CP" for commercial, "ZP" for gift, null for all)
     * @param pageNum   页码
     * @param pageSize  每页条数
     *
     * @return 分页结果
     */
    public TableDataInfo<StockChangeRecordVO> getStockChangeRecords(Long productId, String storeId, String productType, int pageNum, int pageSize)
    {
        TableDataInfo<StockChangeRecordVO> response = DataPermissionHelper.ignore(() ->
        {
            List<StockChangeRecordVO> records = new ArrayList<>();

            // 1. 查询出入库数据 (出库、跨店入库、自增入库、员工福利、客户赠品、外围市场)
            QueryWrapper<HmIssueReceiptRecords> issueReceiptQuery = new QueryWrapper<>();
            issueReceiptQuery.eq("record_product_id", productId);
            issueReceiptQuery.and(wrapper -> wrapper
                .eq("record_start_location", storeId)
                .or()
                .eq("record_end_location", storeId)
            );
            issueReceiptQuery.eq("del_flag", 0);
            // 根据 productType 过滤出入库记录
            if (StringUtils.isNotBlank(productType)) {
                if ("CP".equals(productType)) {
                    issueReceiptQuery.and(wrapper -> wrapper
                        .eq("record_type", ReceiptIssueRecordTypeEnum.OUTBOUND.getCode())
                        .or()
                        .eq("record_type", ReceiptIssueRecordTypeEnum.SELF_ADDED_RECEIPT.getCode())
                        .or()
                        .eq("record_type", ReceiptIssueRecordTypeEnum.INBOUND.getCode())
                        .or()
                        .eq("record_type", ReceiptIssueRecordTypeEnum.FRINGE_MARKET.getCode())
                    );
                } else if ("ZP".equals(productType)) {
                    issueReceiptQuery.and(wrapper -> wrapper
                        .eq("record_type", ReceiptIssueRecordTypeEnum.EMPLOYEE_BENEFITS.getCode())
                        .or()
                        .eq("record_type", ReceiptIssueRecordTypeEnum.CUSTOMER_GIFTS.getCode())
                    );
                }
            }
            List<HmIssueReceiptRecords> issueReceiptRecords = issueReceiptRecordsMapper.selectList(issueReceiptQuery);

            for (HmIssueReceiptRecords record : issueReceiptRecords)
            {
                StockChangeRecordVO changeRecord = new StockChangeRecordVO();
                changeRecord.setRecordId(record.getRecordId());
                changeRecord.setProductId(productId);
                changeRecord.setProductName(record.getRecordProductName());
                changeRecord.setChangeNum(record.getRecordNum());
                changeRecord.setChangeTime(record.getCreateTime());
                changeRecord.setRecordEndLocation(record.getRecordEndLocation()); // 终点仓库
                changeRecord.setRecordStartLocation(record.getRecordStartLocation()); // 起点仓库
                changeRecord.setRemark(record.getRemark());

                // 根据 recordType 设置 recordType 描述
                if (ReceiptIssueRecordTypeEnum.SELF_ADDED_RECEIPT.getCode().equals(record.getRecordType())) {
                    changeRecord.setRecordType(ReceiptIssueRecordTypeEnum.SELF_ADDED_RECEIPT.getDescription());
                } else if (ReceiptIssueRecordTypeEnum.OUTBOUND.getCode().equals(record.getRecordType())) {
                    changeRecord.setRecordType(ReceiptIssueRecordTypeEnum.OUTBOUND.getDescription());
                } else if (ReceiptIssueRecordTypeEnum.CUSTOMER_GIFTS.getCode().equals(record.getRecordType())) {
                    changeRecord.setRecordType(ReceiptIssueRecordTypeEnum.CUSTOMER_GIFTS.getDescription());
                } else if (ReceiptIssueRecordTypeEnum.EMPLOYEE_BENEFITS.getCode().equals(record.getRecordType())) {
                    changeRecord.setRecordType(ReceiptIssueRecordTypeEnum.EMPLOYEE_BENEFITS.getDescription());
                } else if (ReceiptIssueRecordTypeEnum.INBOUND.getCode().equals(record.getRecordType())) {
                    changeRecord.setRecordType(ReceiptIssueRecordTypeEnum.INBOUND.getDescription());
                } else if (ReceiptIssueRecordTypeEnum.FRINGE_MARKET.getCode().equals(record.getRecordType())) {
                    changeRecord.setRecordType(ReceiptIssueRecordTypeEnum.FRINGE_MARKET.getDescription());
                } else if (StockChangeTypeEnum.RETURN_RECEIPT.getCode().equals(record.getRecordType())) { // 退货入库
                    changeRecord.setRecordType(StockChangeTypeEnum.RETURN_RECEIPT.getDescription());
                }
                records.add(changeRecord);
            }

            // 2. 查询销售订单提货记录 (HmSaleOrderPickUp)
            QueryWrapper<HmSaleOrder> saleOrderQuery = new QueryWrapper<>();
            saleOrderQuery.eq("sale_product_id", productId); // 销售的产品ID
            saleOrderQuery.eq("sale_dept", storeId); // 销售店铺
            saleOrderQuery.eq("del_flag", 0);

            // 根据 productType 过滤销售订单
            if (StringUtils.isNotBlank(productType)) {
                saleOrderQuery.apply("EXISTS (SELECT 1 FROM hm_product p WHERE p.product_id = hm_sale_order.sale_product_id AND p.del_flag = 0 " +
                    (!"ZP".equals(productType) ? "AND p.is_commercial_product = TRUE" : "AND p.is_gift_product = TRUE") +
                    ")");
            }

            List<HmSaleOrder> saleOrders = saleOrderMapper.selectList(saleOrderQuery);

            Optional.ofNullable(saleOrders).orElse(new ArrayList<>()).forEach(saleOrder ->
            {
                // 提货记录 (来自 hm_sale_order_pick_up)
                QueryWrapper<HmSaleOrderPickUp> pickUpQuery = new QueryWrapper<>();
                pickUpQuery.eq("sale_order_id", saleOrder.getSaleId());
                pickUpQuery.eq("pick_up_type", OrderStatus.PICK_UP.getCode()); // 提货
                pickUpQuery.eq("sale_product_id", productId); // 提货商品id
                pickUpQuery.eq("del_flag", 0);
                List<HmSaleOrderPickUp> pickUpRecords = saleOrderPickUpMapper.selectList(pickUpQuery);

                for (HmSaleOrderPickUp record : pickUpRecords)
                {
                    StockChangeRecordVO changeRecord = new StockChangeRecordVO();
                    changeRecord.setRecordId(record.getPickUpId());
                    changeRecord.setRecordType(StockTypeEnum.PICK_UP.getDescription());
                    changeRecord.setChangeNum(record.getPickUpNum());
                    changeRecord.setOrderId(saleOrder.getSaleId()); // 订单id
                    changeRecord.setProductId(productId);
                    changeRecord.setChangeTime(record.getPickUpTime());
                    changeRecord.setRemark(record.getRemark());
                    changeRecord.setOperatorId(saleOrder.getCustomerId()); // 客户id
                    changeRecord.setProof(record.getFile()); // 证明材料
                    records.add(changeRecord);
                }
            });

            // 3. 查询补充提货出库记录 (新增)
            QueryWrapper<HmSupplementaryPickupRecord> supplementaryPickupQuery = new QueryWrapper<>();
            supplementaryPickupQuery.eq("supplementary_product_id", productId);
            supplementaryPickupQuery.eq("pickup_dept_id", storeId);
            supplementaryPickupQuery.eq("status", "NORMAL"); // 只统计正常状态的
            supplementaryPickupQuery.eq("del_flag", false);

            // 根据 productType 过滤补充提货记录
            if (StringUtils.isNotBlank(productType)) {
                supplementaryPickupQuery.apply("EXISTS (SELECT 1 FROM hm_product p WHERE p.product_id = hm_supplementary_pickup_record.supplementary_product_id AND p.del_flag = 0 " +
                    (!"ZP".equals(productType) ? "AND p.is_commercial_product = TRUE" : "AND p.is_gift_product = TRUE") +
                    ")");
            }
            List<HmSupplementaryPickupRecord> supplementaryRecords = supplementaryPickupRecordMapper.selectList(supplementaryPickupQuery);

            for (HmSupplementaryPickupRecord record : supplementaryRecords) {
                StockChangeRecordVO changeRecord = new StockChangeRecordVO();
                changeRecord.setRecordId(record.getSupplementaryPickupId());
                changeRecord.setRecordType(StockChangeTypeEnum.SUPPLEMENTARY_OUTBOUND.getDescription()); // 补充提货出库
                changeRecord.setChangeNum(record.getSupplementaryQuantity());
                changeRecord.setOrderId(record.getOriginalSaleId()); // 关联到原始订单ID
                changeRecord.setProductId(record.getSupplementaryProductId());
                changeRecord.setProductName(record.getSupplementaryProductName());
                changeRecord.setChangeTime(record.getPickupTime());
                changeRecord.setRemark(record.getReason());
                changeRecord.setOperatorId(record.getOperatorId());
                changeRecord.setOperator(record.getOperatorName());
                changeRecord.setProof(record.getProofFiles());
                records.add(changeRecord);
            }


            // 4. 查询删除回增库存数据 (来自 HmSaleOrderPickUp)
            QueryWrapper<HmSaleOrderPickUp> pickUpQueryDelOrder = new QueryWrapper<>();
            pickUpQueryDelOrder.eq("pick_up_type", OrderStatus.DEL_ORDER.getCode()); // 订单删除回填
            pickUpQueryDelOrder.eq("sale_product_id", productId); // 提货商品id
            pickUpQueryDelOrder.eq("del_flag", 0);
            List<HmSaleOrderPickUp> pickUpRecordsDelOrder = saleOrderPickUpMapper.selectList(pickUpQueryDelOrder);
            for (HmSaleOrderPickUp record : pickUpRecordsDelOrder)
            {
                StockChangeRecordVO changeRecord = new StockChangeRecordVO();
                changeRecord.setRecordId(record.getPickUpId());
                changeRecord.setRecordType(StockTypeEnum.DEL_ORDER.getDescription());
                changeRecord.setChangeNum(record.getPickUpNum());
                changeRecord.setOrderId(record.getSaleOrderId()); // 订单id
                changeRecord.setChangeTime(record.getPickUpTime());
                changeRecord.setProductId(productId);
                records.add(changeRecord);
            }

            // 5. 查询自主增加库存 (来自 HmStock)
            HmStock hmStock = baseMapper.selectOne(Wrappers.lambdaQuery(HmStock.class).eq(HmStock::getStockProductId, productId)
                .eq(HmStock::getProductDept, storeId).eq(HmStock::getIsNew, true));
            if (hmStock != null)
            {
                StockChangeRecordVO changeRecord = new StockChangeRecordVO();
                changeRecord.setRecordId(hmStock.getStockId());
                changeRecord.setRecordType(StockTypeEnum.ADD.getDescription()); // 自主增加库存
                changeRecord.setChangeNum(BigDecimal.valueOf(hmStock.getNewNum())); // 数量
                changeRecord.setChangeTime(hmStock.getCreateTime()); // 时间
                changeRecord.setProductId(productId);
                records.add(changeRecord);
            }
            // 分页
            int total = records.size();
            int start = (pageNum - 1) * pageSize;
            int end = Math.min(start + pageSize, total);
            List<StockChangeRecordVO> pageRecords = records.subList(start, end);

            return new TableDataInfo<>(pageRecords, total);
        });
        return response;

    }
}
